package com.cloudbroker.bcs.common.service.base;

import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.cloudbroker.bcs.common.constants.BasicErrorCodes;
import com.cloudbroker.bcs.common.dao.base.DAOBase;
import com.cloudbroker.bcs.common.entity.Pageable;
import com.cloudbroker.bcs.common.entity.Updatable;
import com.cloudbroker.bcs.common.exception.HSBCSErrInfoException;
import com.cloudbroker.bcs.common.model.Pagination;
import com.cloudbroker.bcs.common.model.SortMarker;
import com.cloudbroker.bcs.common.util.ValueUtil;

public abstract class ServiceImplBase<T extends Pageable, K> implements ServiceBase<T, K> {
    
    private static final Logger LOGGER = LoggerFactory.getLogger(ServiceImplBase.class);
    
    public void save(T entity) {
        if (entity instanceof Updatable) {
            Updatable updatable = (Updatable) entity;
            updatable.setUpdate_version(0L);
        }
        getDAO().save(entity);
    }
    
    public T get(K key) {
        if (ValueUtil.isEmpty(key)) {
            return null;
        }
        return getDAO().get(key);
    }
    
    @Override
    public Integer count(T example) {
        return getDAO().count(example);
    }
    
    public List<T> query(T example) {
        return getDAO().query(example);
    }
    
    public List<T> queryAll() {
        return getDAO().query(null);
    }
    
    @Override
    public List<T> queryWithPagination(T example, Pagination page) {
        int count = count(example);
        if (null == page) {
            page = example.getPage();
        }
        page.setTotal_item_num(count);
        page.calc();
        example.setPage(page);
        return query(example);
    }
    
    @Override
    public List<T> queryWithPagination(T example, Pagination page, SortMarker... sortMarkers) {
        example.addSortMarker(sortMarkers);
        return queryWithPagination(example, page);
    }
    
    public int updateCAS(T entity) {
        return updateCAS(entity, true);
    }
    
    public int updateCAS(T entity, boolean throwException) {
        int updateNum = update(entity);
        if (0 == updateNum) {
            if (throwException) {
                throw new HSBCSErrInfoException(BasicErrorCodes.CONCURRENT_MODIFY);
            } else {
                LOGGER.error("concurrent modify: " + entity);
            }
        } else {
            if (entity instanceof Updatable) {
                Updatable updatable = (Updatable) entity;
                long updateVersion = ValueUtil.getLong(updatable);
                updatable.setUpdate_version(updateVersion + 1);
            }
        }
        return updateNum;
    }
    
    public int update(T entity) {
        return getDAO().update(entity);
    }
    
    public int delete(K key) {
        return getDAO().delete(key);
    }

    public int deleteByEntity(T entity){
        return getDAO().deleteByEntity(entity);
    }

    public T getByEntity(T entity){
        return getDAO().getByEntity(entity);
    }

    protected abstract DAOBase<T, K> getDAO();
    
}
